package handler

import (
	"context"
	"fmt"
	"time"

	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm/clause"
	"sale_system/inventory_srv/global"
	"sale_system/inventory_srv/model"
	"sale_system/inventory_srv/proto"
	"sale_system/inventory_srv/service"
)

type InventoryServer struct {
	proto.UnimplementedInventoryServer // 一定需要实现这个接口
	redisService                       *service.RedisInventoryService
}

// NewInventoryServer 创建库存服务实例
func NewInventoryServer() *InventoryServer {
	return &InventoryServer{
		redisService: service.NewRedisInventoryService(),
	}
}

func (s *InventoryServer) mustEmbedUnimplementedGoodsServer() {
	//TODO implement me
	panic("implement me")
}

func (s *InventoryServer) SetInv(ctx context.Context, request *proto.GoodsInvInfo) (*emptypb.Empty, error) {
	var inv model.Inventory
	global.DB.Where(&model.Inventory{Goods: request.GoodsId}).First(&inv) // 读取对象

	// 设置库存
	inv.Goods = request.GoodsId
	inv.Stocks = request.Num

	global.DB.Save(&inv)

	return &emptypb.Empty{}, nil
}

func (s *InventoryServer) InvDetail(ctx context.Context, request *proto.GoodsInvInfo) (*proto.GoodsInvInfo, error) {

	var inv model.Inventory
	if result := global.DB.Where(&model.Inventory{Goods: request.GoodsId}).First(&inv); result.RowsAffected == 0 {

		return nil, status.Error(codes.NotFound, "没有库存信息")
	}

	// 返回可用库存（总库存 - 冻结库存）
	availableStock := inv.Stocks - inv.Freeze
	return &proto.GoodsInvInfo{
		GoodsId: inv.Goods,
		Num:     availableStock,
	}, nil
}

func (s *InventoryServer) ReBack(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {

	// 库存归还： 其实我们本质上并不用使用，我们库存归还的模块，直接往InventoryReBack发送库存归还消息即可
	tx := global.DB.Begin()
	// 下订单时需要扣减库存
	for _, goodsInfo := range request.GoodsInfo { // 先从切片中取出单个产品
		var inv model.Inventory

		result := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where(&model.Inventory{Goods: goodsInfo.GoodsId}).First(&inv)
		if result.RowsAffected == 0 {
			tx.Rollback() // 只要失败就回滚
			return nil, status.Error(codes.InvalidArgument, "没有库存信息")
		}

		// 进行库存回复
		inv.Stocks = inv.Stocks + goodsInfo.Num // 还是会存在并发导致的数据不一致的问题，需要分布式锁
		tx.Save(&inv)
	}
	tx.Commit()
	return &emptypb.Empty{}, nil
}

// SellSad mysql悲观锁方案
func (s *InventoryServer) SellSad(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {

	tx := global.DB.Begin() // 注意后续数据库操作都需要通过 tx！！！

	// 下订单时需要扣减库存
	for _, goodsInfo := range request.GoodsInfo { // 先从切片中取出单个产品

		var inv model.Inventory
		// 添加数据库的悲观锁---行锁，对Goods = GoodsId这行数据进行加锁
		result := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where(&model.Inventory{Goods: goodsInfo.GoodsId}).First(&inv)
		if result.RowsAffected == 0 {
			tx.Rollback() // 只要失败就回滚
			return nil, status.Error(codes.InvalidArgument, "没有库存信息")
		}
		// 取到了库存 但是库存少于下单量
		if inv.Stocks < goodsInfo.Num {
			tx.Rollback()
			zap.S().Errorf("出现超卖")
			return nil, status.Errorf(codes.ResourceExhausted, "库存不足")
		}

		// 进行扣减库存
		inv.Stocks = inv.Stocks - goodsInfo.Num // 通过悲观锁防止并发导致数据不一致问题
		tx.Save(&inv)

	}
	tx.Commit()
	zap.S().Info("库存扣减成功")
	return &emptypb.Empty{}, nil
}

// SellHappy mysql乐观锁方案
func (s *InventoryServer) SellHappy(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {

	tx := global.DB.Begin() // 注意后续数据库操作都需要通过 tx！！！

	// 下订单时需要扣减库存
	for _, goodsInfo := range request.GoodsInfo { // 先从切片中取出单个产品

		var inv model.Inventory
		// 如果因为版本号原因冲突，就需要错误重试
		for {
			result := global.DB.Where(&model.Inventory{Goods: goodsInfo.GoodsId}).First(&inv)
			if result.RowsAffected == 0 {
				tx.Rollback() // 只要失败就回滚
				return nil, status.Error(codes.InvalidArgument, "没有库存信息")
			}
			// 取到了库存 但是库存少于下单量，库存不够了！！！
			if inv.Stocks < goodsInfo.Num {
				tx.Rollback()
				zap.S().Errorf("出现超卖")
				return nil, status.Errorf(codes.ResourceExhausted, "库存不足")
			}

			// 进行扣减库存
			inv.Stocks = inv.Stocks - goodsInfo.Num

			// 结合版本号实现了"乐观锁"
			result = tx.Model(&model.Inventory{}).Select("Stocks", "Version").
				Where("goods=? and version=?", goodsInfo.GoodsId, inv.Version).
				Updates(model.Inventory{Stocks: inv.Stocks, Version: inv.Version + 1})
			if result.RowsAffected == 0 {
				zap.S().Info("商品库存扣除失败，进行重试") // 当库存没了之后，我们在上面判断库存就会返回，退出函数
			} else { // 当前这一次没有出现版本号冲突，进入下一个商品
				break
			}
		}
	}
	tx.Commit()

	return &emptypb.Empty{}, nil
}

// Sell redis分布式锁方案
func (s *InventoryServer) Sell(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {

	tx := global.DB.Begin() // 注意后续数据库操作都需要通过 tx！！！

	sellDetail := model.StockSellDetail{ // 用来维护当前的售卖信息，进行一致性事务的判断
		OrderSn: request.OrderSn,
		Status:  1,
	}

	var details []model.GoodsDetail

	// 下订单时需要扣减库存
	for _, goodsInfo := range request.GoodsInfo { // 先从切片中取出单个产品

		// 维护商品的扣减详细信息
		details = append(details, model.GoodsDetail{
			Goods: goodsInfo.GoodsId,
			Num:   goodsInfo.Num,
		})

		var inv model.Inventory

		// 获得redis分布式锁
		GoodsName := fmt.Sprintf("goods-%d", goodsInfo.GoodsId)
		mutex := global.RedsSync.NewMutex(GoodsName)
		err := mutex.Lock()
		if err != nil {
			tx.Rollback()
			zap.S().Error(err)
			return nil, status.Error(codes.Internal, "获取redis分布式锁异常")
		}

		result := global.DB.Where(&model.Inventory{Goods: goodsInfo.GoodsId}).First(&inv)
		if result.RowsAffected == 0 {
			tx.Rollback() // 只要失败就回滚
			return nil, status.Error(codes.InvalidArgument, "没有库存信息")
		}
		// 取到了库存 但是库存少于下单量
		if inv.Stocks < goodsInfo.Num {
			tx.Rollback()
			zap.S().Errorf("出现超卖")
			return nil, status.Errorf(codes.ResourceExhausted, "库存不足")
		}

		// 进行扣减库存
		inv.Stocks = inv.Stocks - goodsInfo.Num
		tx.Save(&inv)

		ok, err := mutex.Unlock()
		if ok == false || err != nil {
			return nil, status.Error(codes.Internal, "释放redis分布式锁异常")
		}

	}
	sellDetail.Detail = details
	// 将sellDetail存进数据库中
	if result := tx.Create(&sellDetail); result.RowsAffected == 0 {
		tx.Rollback()
		return nil, status.Errorf(codes.Internal, "保存库存扣减历史失败")
	}

	tx.Commit()
	zap.S().Info("库存扣减成功")
	return &emptypb.Empty{}, nil
}

// SellTry TCC Try阶段：预扣减库存
func (s *InventoryServer) SellTry(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	tx := global.DB.Begin()
	
	// 检查是否已经存在该订单的TCC事务记录
	var tccTransaction model.TccTransaction
	if result := tx.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected > 0 {
		// 如果已经存在，检查状态
		if tccTransaction.Status == 0 {
			// 还在Try阶段，直接返回成功（幂等性）
			tx.Commit()
			return &emptypb.Empty{}, nil
		} else if tccTransaction.Status == 1 {
			// 已经Confirm，返回成功
			tx.Commit()
			return &emptypb.Empty{}, nil
		} else {
			// 已经Cancel，返回错误
			tx.Rollback()
			return nil, status.Error(codes.InvalidArgument, "订单已取消，无法重新预扣减")
		}
	}
	
	// 检查库存是否足够（可用库存 = Stocks - Freeze）
	for _, goodsInfo := range request.GoodsInfo {
		var inv model.Inventory
		result := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("goods = ?", goodsInfo.GoodsId).First(&inv)
		if result.RowsAffected == 0 {
			tx.Rollback()
			return nil, status.Error(codes.InvalidArgument, "没有库存信息")
		}
		
		// 检查可用库存是否足够（实际库存 - 冻结库存）
		availableStock := inv.Stocks - inv.Freeze
		if availableStock < goodsInfo.Num {
			tx.Rollback()
			zap.S().Errorf("库存不足，商品ID: %d, 需要: %d, 可用库存: %d (总库存: %d, 冻结: %d)", 
				goodsInfo.GoodsId, goodsInfo.Num, availableStock, inv.Stocks, inv.Freeze)
			return nil, status.Errorf(codes.ResourceExhausted, "库存不足")
		}
	}
	
	// 冻结库存（增加冻结数量，不扣减实际库存）
	for _, goodsInfo := range request.GoodsInfo {
		var inv model.Inventory
		tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("goods = ?", goodsInfo.GoodsId).First(&inv)
		
		// 增加冻结库存
		inv.Freeze = inv.Freeze + goodsInfo.Num
		tx.Save(&inv)
		
		// 记录预扣减信息
		preDeduct := model.PreDeductInventory{
			OrderSn: request.OrderSn,
			Goods:   goodsInfo.GoodsId,
			Num:     goodsInfo.Num,
			Status:  0, // 预扣减状态
		}
		tx.Create(&preDeduct)
	}
	
	// 创建TCC事务记录
	var details []model.GoodsDetail
	for _, goodsInfo := range request.GoodsInfo {
		details = append(details, model.GoodsDetail{
			Goods: goodsInfo.GoodsId,
			Num:   goodsInfo.Num,
		})
	}
	
	tccTransaction = model.TccTransaction{
		OrderSn: request.OrderSn,
		Status:  0, // Try阶段
		Detail:  details,
		TryTime: time.Now().Unix(),
	}
	
	tx.Create(&tccTransaction)
	tx.Commit()
	
	zap.S().Infof("TCC Try阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellConfirm TCC Confirm阶段：确认扣减库存
func (s *InventoryServer) SellConfirm(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	tx := global.DB.Begin()
	
	// 检查TCC事务记录
	var tccTransaction model.TccTransaction
	if result := tx.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected == 0 {
		tx.Rollback()
		return nil, status.Error(codes.InvalidArgument, "未找到对应的TCC事务记录")
	}
	
	// 检查状态
	if tccTransaction.Status == 1 {
		// 已经Confirm，直接返回成功（幂等性）
		tx.Commit()
		return &emptypb.Empty{}, nil
	} else if tccTransaction.Status == 2 {
		// 已经Cancel，返回错误
		tx.Rollback()
		return nil, status.Error(codes.InvalidArgument, "订单已取消，无法确认")
	}
	
	// 确认扣减库存：实际扣减库存，清空冻结库存
	var preDeducts []model.PreDeductInventory
	tx.Where("order_sn = ?", request.OrderSn).Find(&preDeducts)
	
	for _, preDeduct := range preDeducts {
		var inv model.Inventory
		tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("goods = ?", preDeduct.Goods).First(&inv)
		
		// 实际扣减库存
		inv.Stocks = inv.Stocks - preDeduct.Num
		// 清空冻结库存
		inv.Freeze = inv.Freeze - preDeduct.Num
		tx.Save(&inv)
		
		// 更新预扣减记录状态为确认
		preDeduct.Status = 1 // 确认扣减
		tx.Save(&preDeduct)
	}
	
	// 更新TCC事务状态
	tccTransaction.Status = 1 // Confirm阶段
	tccTransaction.ConfirmTime = time.Now().Unix()
	tx.Save(&tccTransaction)
	
	// 创建库存扣减历史记录
	sellDetail := model.StockSellDetail{
		OrderSn: request.OrderSn,
		Status:  1, // 已扣减
		Detail:  tccTransaction.Detail,
	}
	tx.Create(&sellDetail)
	
	tx.Commit()
	
	zap.S().Infof("TCC Confirm阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellCancel TCC Cancel阶段：取消扣减，恢复库存
func (s *InventoryServer) SellCancel(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	tx := global.DB.Begin()
	
	// 检查TCC事务记录
	var tccTransaction model.TccTransaction
	if result := tx.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected == 0 {
		tx.Rollback()
		return nil, status.Error(codes.InvalidArgument, "未找到对应的TCC事务记录")
	}
	
	// 检查状态
	if tccTransaction.Status == 2 {
		// 已经Cancel，直接返回成功（幂等性）
		tx.Commit()
		return &emptypb.Empty{}, nil
	} else if tccTransaction.Status == 1 {
		// 已经Confirm，返回错误
		tx.Rollback()
		return nil, status.Error(codes.InvalidArgument, "订单已确认，无法取消")
	}
	
	// 取消冻结：减少冻结库存，不扣减实际库存
	var preDeducts []model.PreDeductInventory
	tx.Where("order_sn = ?", request.OrderSn).Find(&preDeducts)
	
	for _, preDeduct := range preDeducts {
		var inv model.Inventory
		tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("goods = ?", preDeduct.Goods).First(&inv)
		
		// 减少冻结库存（恢复可用库存）
		inv.Freeze = inv.Freeze - preDeduct.Num
		tx.Save(&inv)
		
		// 更新预扣减记录状态为取消
		preDeduct.Status = 2 // 取消扣减
		tx.Save(&preDeduct)
	}
	
	// 更新TCC事务状态
	tccTransaction.Status = 2 // Cancel阶段
	tccTransaction.CancelTime = time.Now().Unix()
	tx.Save(&tccTransaction)
	
	tx.Commit()
	
	zap.S().Infof("TCC Cancel阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellFlash Redis秒杀方案
func (s *InventoryServer) SellFlash(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	// 使用Redis进行高并发库存扣减
	for _, goodsInfo := range request.GoodsInfo {
		// 使用Redis分布式锁确保原子性
		lockKey := s.redisService.GetInventoryLockKey(goodsInfo.GoodsId)
		mutex := global.RedsSync.NewMutex(lockKey)
		
		if err := mutex.Lock(); err != nil {
			zap.S().Errorf("获取分布式锁失败: %v", err)
			return nil, status.Error(codes.Internal, "获取分布式锁异常")
		}
		
		// 执行库存扣减
		if err := s.redisService.DeductInventory(goodsInfo.GoodsId, goodsInfo.Num, request.OrderSn); err != nil {
			mutex.Unlock()
			zap.S().Errorf("Redis库存扣减失败: %v", err)
			return nil, status.Errorf(codes.ResourceExhausted, "库存不足: %v", err)
		}
		
		// 释放锁
		if ok, err := mutex.Unlock(); !ok || err != nil {
			zap.S().Errorf("释放分布式锁失败: %v", err)
		}
	}
	
	zap.S().Infof("Redis秒杀库存扣减成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellFlashTry Redis秒杀TCC Try阶段
func (s *InventoryServer) SellFlashTry(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	// 检查是否已经存在该订单的TCC事务记录
	var tccTransaction model.TccTransaction
	if result := global.DB.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected > 0 {
		// 如果已经存在，检查状态
		if tccTransaction.Status == 0 {
			// 还在Try阶段，直接返回成功（幂等性）
			return &emptypb.Empty{}, nil
		} else if tccTransaction.Status == 1 {
			// 已经Confirm，返回成功
			return &emptypb.Empty{}, nil
		} else {
			// 已经Cancel，返回错误
			return nil, status.Error(codes.InvalidArgument, "订单已取消，无法重新预扣减")
		}
	}
	
	// 使用Redis进行库存冻结
	for _, goodsInfo := range request.GoodsInfo {
		lockKey := s.redisService.GetInventoryLockKey(goodsInfo.GoodsId)
		mutex := global.RedsSync.NewMutex(lockKey)
		
		if err := mutex.Lock(); err != nil {
			zap.S().Errorf("获取分布式锁失败: %v", err)
			return nil, status.Error(codes.Internal, "获取分布式锁异常")
		}
		
		// 冻结库存
		if err := s.redisService.FreezeInventory(goodsInfo.GoodsId, goodsInfo.Num, request.OrderSn); err != nil {
			mutex.Unlock()
			zap.S().Errorf("Redis库存冻结失败: %v", err)
			return nil, status.Errorf(codes.ResourceExhausted, "库存不足: %v", err)
		}
		
		// 释放锁
		if ok, err := mutex.Unlock(); !ok || err != nil {
			zap.S().Errorf("释放分布式锁失败: %v", err)
		}
	}
	
	// 创建TCC事务记录
	var details []model.GoodsDetail
	for _, goodsInfo := range request.GoodsInfo {
		details = append(details, model.GoodsDetail{
			Goods: goodsInfo.GoodsId,
			Num:   goodsInfo.Num,
		})
	}
	
	tccTransaction = model.TccTransaction{
		OrderSn: request.OrderSn,
		Status:  0, // Try阶段
		Detail:  details,
		TryTime: time.Now().Unix(),
	}
	
	global.DB.Create(&tccTransaction)
	
	zap.S().Infof("Redis秒杀TCC Try阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellFlashConfirm Redis秒杀TCC Confirm阶段
func (s *InventoryServer) SellFlashConfirm(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	// 检查TCC事务记录
	var tccTransaction model.TccTransaction
	if result := global.DB.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected == 0 {
		return nil, status.Error(codes.InvalidArgument, "未找到对应的TCC事务记录")
	}
	
	// 检查状态
	if tccTransaction.Status == 1 {
		// 已经Confirm，直接返回成功（幂等性）
		return &emptypb.Empty{}, nil
	} else if tccTransaction.Status == 2 {
		// 已经Cancel，返回错误
		return nil, status.Error(codes.InvalidArgument, "订单已取消，无法确认")
	}
	
	// 确认扣减：将冻结库存转换为实际扣减
	for _, goodsInfo := range request.GoodsInfo {
		lockKey := s.redisService.GetInventoryLockKey(goodsInfo.GoodsId)
		mutex := global.RedsSync.NewMutex(lockKey)
		
		if err := mutex.Lock(); err != nil {
			zap.S().Errorf("获取分布式锁失败: %v", err)
			return nil, status.Error(codes.Internal, "获取分布式锁异常")
		}
		
		// 解冻并扣减库存
		if err := s.redisService.UnfreezeInventory(goodsInfo.GoodsId, goodsInfo.Num, request.OrderSn); err != nil {
			mutex.Unlock()
			zap.S().Errorf("Redis库存解冻失败: %v", err)
			return nil, status.Error(codes.Internal, "库存操作失败")
		}
		
		// 实际扣减库存
		if err := s.redisService.DeductInventory(goodsInfo.GoodsId, goodsInfo.Num, request.OrderSn); err != nil {
			mutex.Unlock()
			zap.S().Errorf("Redis库存扣减失败: %v", err)
			return nil, status.Error(codes.Internal, "库存操作失败")
		}
		
		// 释放锁
		if ok, err := mutex.Unlock(); !ok || err != nil {
			zap.S().Errorf("释放分布式锁失败: %v", err)
		}
	}
	
	// 更新TCC事务状态
	tccTransaction.Status = 1 // Confirm阶段
	tccTransaction.ConfirmTime = time.Now().Unix()
	global.DB.Save(&tccTransaction)
	
	// 创建库存扣减历史记录
	sellDetail := model.StockSellDetail{
		OrderSn: request.OrderSn,
		Status:  1, // 已扣减
		Detail:  tccTransaction.Detail,
	}
	global.DB.Create(&sellDetail)
	
	zap.S().Infof("Redis秒杀TCC Confirm阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// SellFlashCancel Redis秒杀TCC Cancel阶段
func (s *InventoryServer) SellFlashCancel(ctx context.Context, request *proto.SellInfo) (*emptypb.Empty, error) {
	// 检查TCC事务记录
	var tccTransaction model.TccTransaction
	if result := global.DB.Where("order_sn = ?", request.OrderSn).First(&tccTransaction); result.RowsAffected == 0 {
		return nil, status.Error(codes.InvalidArgument, "未找到对应的TCC事务记录")
	}
	
	// 检查状态
	if tccTransaction.Status == 2 {
		// 已经Cancel，直接返回成功（幂等性）
		return &emptypb.Empty{}, nil
	} else if tccTransaction.Status == 1 {
		// 已经Confirm，返回错误
		return nil, status.Error(codes.InvalidArgument, "订单已确认，无法取消")
	}
	
	// 取消冻结：解冻库存
	for _, goodsInfo := range request.GoodsInfo {
		lockKey := s.redisService.GetInventoryLockKey(goodsInfo.GoodsId)
		mutex := global.RedsSync.NewMutex(lockKey)
		
		if err := mutex.Lock(); err != nil {
			zap.S().Errorf("获取分布式锁失败: %v", err)
			return nil, status.Error(codes.Internal, "获取分布式锁异常")
		}
		
		// 解冻库存
		if err := s.redisService.UnfreezeInventory(goodsInfo.GoodsId, goodsInfo.Num, request.OrderSn); err != nil {
			mutex.Unlock()
			zap.S().Errorf("Redis库存解冻失败: %v", err)
			return nil, status.Error(codes.Internal, "库存操作失败")
		}
		
		// 释放锁
		if ok, err := mutex.Unlock(); !ok || err != nil {
			zap.S().Errorf("释放分布式锁失败: %v", err)
		}
	}
	
	// 更新TCC事务状态
	tccTransaction.Status = 2 // Cancel阶段
	tccTransaction.CancelTime = time.Now().Unix()
	global.DB.Save(&tccTransaction)
	
	zap.S().Infof("Redis秒杀TCC Cancel阶段成功，订单号: %s", request.OrderSn)
	return &emptypb.Empty{}, nil
}

// GetInventoryFromRedis 从Redis获取库存信息
func (s *InventoryServer) GetInventoryFromRedis(ctx context.Context, request *proto.GoodsInvInfo) (*proto.GoodsInvInfo, error) {
	availableStock, err := s.redisService.GetAvailableStock(request.GoodsId)
	if err != nil {
		zap.S().Errorf("获取Redis库存失败: %v", err)
		return nil, status.Error(codes.Internal, "获取库存信息失败")
	}
	
	return &proto.GoodsInvInfo{
		GoodsId: request.GoodsId,
		Num:     availableStock,
	}, nil
}

// SetInventoryToRedis 设置库存到Redis
func (s *InventoryServer) SetInventoryToRedis(ctx context.Context, request *proto.GoodsInvInfo) (*emptypb.Empty, error) {
	// 从数据库获取完整库存信息
	var inv model.Inventory
	if result := global.DB.Where("goods = ?", request.GoodsId).First(&inv); result.RowsAffected == 0 {
		return nil, status.Error(codes.NotFound, "商品库存不存在")
	}
	
	// 更新库存数量
	inv.Stocks = request.Num
	
	// 保存到数据库
	global.DB.Save(&inv)
	
	// 同步到Redis
	redisInv := model.RedisInventory{
		GoodsId:    inv.Goods,
		Stocks:     inv.Stocks,
		Freeze:     inv.Freeze,
		Version:    inv.Version,
		UpdateTime: time.Now().Unix(),
	}
	
	if err := s.redisService.SetInventoryToRedis(request.GoodsId, &redisInv); err != nil {
		zap.S().Errorf("同步库存到Redis失败: %v", err)
		return nil, status.Error(codes.Internal, "同步库存失败")
	}
	
	return &emptypb.Empty{}, nil
}

// StartInventorySyncWorker 启动库存同步工作协程
func (s *InventoryServer) StartInventorySyncWorker(ctx context.Context) {
	s.redisService.StartSyncWorker(ctx)
}
